﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using DevExpress.Web.ASPxCallback;

namespace TireService.Web.UserControls
{
    public partial class ucServiceRouteSimulation : System.Web.UI.UserControl
    {

        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void callbackServiceRouteSimulationPanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            // Get values from client (0: ServiceCarId, 1: ScheduleDate, 2: ContainerId)
            string[] param = e.Parameter.Split('|');

            int ServiceCarId = Convert.ToInt32(param[0]);
            DateTime ScheduleDate = Convert.ToDateTime(param[1]);
            int ContainerId = Convert.ToInt32(param[2]);

            LoadUserControl(ServiceCarId, ScheduleDate, ContainerId);
        }

        /// <summary>
        /// Public function for loading usercontrol
        /// </summary>
        public void LoadUserControl(int ServiceCarId, DateTime ScheduleDate, int ContainerId)
        {
            // Show usercontrol form
            pcServiceRouteSimulation.Visible = true;

            // Initiate datalayer
            TireServiceDB db = new TireServiceDB();

            // Bind gridview with current route
            List<ServiceCarScheduleDetailView> details = db.ServiceCarScheduleDetailViews.Where(p => p.ScheduleDate == ScheduleDate & p.ServiceCarId == ServiceCarId & p.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.ServiceDrive).ToList();

            // Reset optimized plan if stored from earlier user actions
            Session["NewServiceSchedulePlan"] = "";

            if (details.Count != 0)
            {
                gvCurrentRoute.DataSource = details;
                gvCurrentRoute.DataBind();

                Container container = db.GetContainer(ContainerId);

                //lblContainerAddress.Text = container.Address + "," + container.ZipCode + " " + container.City;
                txtStartAddress.Text = container.Address + "," + container.ZipCode + " " + container.City;
                txtEndAddress.Text = container.Address + "," + container.ZipCode + " " + container.City;
            }
            else
            {
                // Error
                throw new ArgumentException("Plan indeholder pt. ingen udkørsler");
            }
        }

        /// <summary>
        /// Gridview function that runs when databinding - Changes colors
        /// </summary>
        protected void gvCurrentRoute_HtmlRowPrepared(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewTableRowEventArgs e)
        {
            if (e.RowType != DevExpress.Web.ASPxGridView.GridViewRowType.Data) return;

            int servicetype = Convert.ToInt32(gvCurrentRoute.GetRowValuesByKeyValue(e.KeyValue, "ScheduleDetailTypeId"));

            if (servicetype == (int)Shared.ScheduleDetailType.Available)
            {
                e.Row.BackColor = System.Drawing.Color.White;
            }
            if (servicetype == (int)Shared.ScheduleDetailType.Blocked)
            {
                e.Row.BackColor = System.Drawing.Color.Red;
            }
            if (servicetype == (int)Shared.ScheduleDetailType.ServiceDrive)
            {
                // Get customerconfirmed value - based on that rows will be formated
                bool CustomerConfirmed = Convert.ToBoolean(gvCurrentRoute.GetRowValuesByKeyValue(e.KeyValue, "CustomerConfirmed"));

                if (CustomerConfirmed)
                {
                    e.Row.BackColor = System.Drawing.Color.DarkGreen;
                }
                else
                {

                    e.Row.BackColor = System.Drawing.Color.Orange;
                }
            }
        }
        
        /// <summary>
        /// Callback function that shows new sequence for scheduledetail
        /// </summary>
        protected void callBackShowOptimizedPlan_Callback(object sender, CallbackEventArgs e)
        {
            try
            {
                // Get values from client (0: ServiceCarId, 1: ScheduleDate, 2: ContainerId, 3-X: NewScheduleSequence)
                string parameters = e.Parameter.Replace(",", "|");
                string[] param = parameters.Split('|');

                int ServiceCarId = Convert.ToInt32(param[0]);
                DateTime ScheduleDate = Convert.ToDateTime(param[1]);
                int ContainerId = Convert.ToInt32(param[2]); // Not used in this function

                // Initiate datalayer
                TireServiceDB db = new TireServiceDB();

                // Bind gridview with schedule detail to optimize
                List<ServiceCarScheduleDetailView> details_all = db.ServiceCarScheduleDetailViews.Where(p => p.ScheduleDate == ScheduleDate & p.ServiceCarId == ServiceCarId).ToList();
                List<ServiceCarScheduleDetailView> details_servicedrive = details_all.Where(p => p.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.ServiceDrive).OrderBy(p => p.SequenceNumber).ToList();
                List<ServiceCarScheduleDetailView> details_noneservicedrive = details_all.Where(p => p.ScheduleDetailTypeId != (int)Shared.ScheduleDetailType.ServiceDrive).OrderBy(p => p.SequenceNumber).ToList();
                List<ServiceCarScheduleDetailView> details_newsequence = new List<ServiceCarScheduleDetailView>();

                if (details_servicedrive == null)
                {
                    // Error
                    throw new ArgumentException("Servicekørsler blev ikke fundet");
                }

                // Handle records with ServiceDrive type - give them new sequence number
                int sequence_count = 0;
                foreach (ServiceCarScheduleDetailView detail in details_servicedrive)
                {
                    for (int i = 3; i < param.Length; i++)
                    {
                        if (sequence_count == Convert.ToInt32(param[i]))
                        {
                            ServiceCarScheduleDetailView detail_newsequence = new ServiceCarScheduleDetailView();
                            detail_newsequence = detail;
                            detail_newsequence.SequenceNumber = Convert.ToInt32(i-2);

                            details_newsequence.Add(detail_newsequence);
                        }    
                    }

                    sequence_count += 1;
                }

                // Handle all other servicedetails that is NOT of type ServiceDrive
                //TODO: CODE DOES NOT CURRENTLY TAKE BLOCKED SCHEDULEDETAILS INTO CONSIDERATION - THEY WILL ALSO BE MOVED AROUND
                int sequenceavailable_count = 1;
                foreach (ServiceCarScheduleDetailView detail in details_noneservicedrive)
                {
                    ServiceCarScheduleDetailView detail_newsequence = new ServiceCarScheduleDetailView();
                    detail_newsequence = detail;
                    detail_newsequence.SequenceNumber = Convert.ToInt32(details_servicedrive.Count + sequenceavailable_count);

                    details_newsequence.Add(detail_newsequence);

                    sequenceavailable_count += 1;
                }

                // Update time sequence on new plan - inherit based on new sequence number
                foreach (ServiceCarScheduleDetailView detail in details_newsequence.OrderBy(p => p.SequenceNumber))
                {
                    ServiceCarScheduleDetailView tempdetail = db.ServiceCarScheduleDetailViews.Single(p => p.ScheduleDate == ScheduleDate & p.ServiceCarId == ServiceCarId & p.SequenceNumber == detail.SequenceNumber);
                    ServiceCarScheduleDetailView detail_newtime = new ServiceCarScheduleDetailView();
                    detail_newtime = detail;
                    detail_newtime.StartTime = tempdetail.StartTime;
                    detail_newtime.EndTime = tempdetail.EndTime;

                    // Remove old detail (without time interval) and add new one including both sequence and timeslot
                    details_newsequence.Remove(detail);
                    details_newsequence.Add(detail_newtime);
                }

                Session["NewServiceSchedulePlan"] = details_newsequence.OrderBy(p => p.SequenceNumber).ToList();
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException("Fejl opstod: " + ex.Message);
            }
        }

        /// <summary>
        /// Callback function that saves new sequence for scheduledetail
        /// </summary>
        protected void callBackSaveOptimizedPlan_Callback(object sender, CallbackEventArgs e)
        {
            try
            {
                // Get values from client (0: ServiceCarId, 1: ScheduleDate, 2: ContainerId)
                string[] param = e.Parameter.Split('|');

                int ServiceCarId = Convert.ToInt32(param[0]);
                DateTime ScheduleDate = Convert.ToDateTime(param[1]);
                int ContainerId = Convert.ToInt32(param[2]); // Not used in this function

                // Initiate datalayer
                TireServiceDB db = new TireServiceDB();

                // Get optimized plan
                List<ServiceCarScheduleDetailView> details_optimized = (List<ServiceCarScheduleDetailView>)Session["NewServiceSchedulePlan"];

                foreach (ServiceCarScheduleDetailView detail_optimized in details_optimized.OrderBy(p => p.SequenceNumber))
                {
                    // Get current schedule    
                    ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(detail_optimized.ServiceCarScheduleDetailId);

                    // Update current schedule with optimized plan
                    detail.SequenceNumber = detail_optimized.SequenceNumber;
                    detail.StartTime = detail_optimized.StartTime;
                    detail.EndTime = detail_optimized.EndTime;
                }

                // Commit changes to database
                db.SubmitChanges();

                // Dispose database connection
                db.Dispose();
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException("Fejl opstod: " + ex.Message);   
            }
        }

        /// <summary>
        /// Postback function that binds new optimized plan to gridview in UI
        /// </summary>
        protected void gvNewRoute_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
        {
            gvNewRoute.DataSource = (List<ServiceCarScheduleDetailView>)Session["NewServiceSchedulePlan"]; // NewPlan;
            gvNewRoute.DataBind();
        }

        ///// <summary>
        ///// Private class used for saving/caching optimized schedule
        ///// </summary>
        //private class OptimizedServiceCarScheduleDetail 
        //{
        //    private int _currentsequence;
        //    private int _newsequence;
        //    private int _servicecarscheduledetailid;
        //    private string _address;

        //    public int CurrentSequence
        //    {
        //        get { return this._currentsequence; }
        //        set
        //        {
        //            this._currentsequence = value;
        //        }
        //    }

        //    public int NewSequence
        //    {
        //        get { return this._newsequence; }
        //        set
        //        {
        //            this._newsequence = value;
        //        }
        //    }

        //    public int ServiceCarScheduleDetailId
        //    {
        //        get { return this._servicecarscheduledetailid; }
        //        set
        //        {
        //            this._servicecarscheduledetailid = value;
        //        }
        //    }

        //    public string Address
        //    {
        //        get { return this._address; }
        //        set
        //        {
        //            this._address = value;
        //        }
        //    }
        //}
    }
}